home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / System / XFD / Developer / autodoc / xfdsub.doc < prev   
Encoding:
Text File  |  2001-09-16  |  15.9 KB  |  432 lines

  1. TABLE OF CONTENTS
  2.  
  3. xfdForeman/--Overview--
  4. xfdSlave/--Overview--
  5. xfdSlave/--HowToStart--
  6. xfdSlave/DecrunchBufferXYZ
  7. xfdSlave/DecrunchSegmentXYZ
  8. xfdSlave/RecogBufferXYZ
  9. xfdSlave/RecogSegmentXYZ
  10. xfdSlave/ScanDataXYZ
  11. xfdSlave/VerifyDataXYZ
  12.  
  13. xfdForeman/--Overview--                               xfdForeman/--Overview--
  14.  
  15. The xfdForeman structure is just some kind of header for external slaves.
  16. It protects the slaves from being executed accidentally by having a small
  17. piece of code (moveq #-1,d0 : rts) in the first 4 bytes.
  18. The master can identify a valid bunch of external slaves by checking the
  19. first few bytes of the file for the foreman identification.
  20. Finally, a foreman holds the pointer to a linked list of slaves and thus
  21. enables the master to work with these slaves.
  22.  
  23. xfdSlave/--Overview--                                   xfdSlave/--Overview--
  24.  
  25. The xfdSlave structure is the heart of the whole library system. Each slave
  26. enables the master to recognize and decrunch packed files. Additionally,
  27. slaves of the type XFDPFB_RELOC can recognize and decrunch segments.
  28. Slaves with XFDPFB_DATA flag set contain routines for data scanning and data
  29. verification.
  30.  
  31. Therefore each slave contains 4 routines that are called from the master.
  32. Pointers to these are stored in xfds_RecogBuffer and xfds_DecrunchBuffer.
  33. XFDPFB_RELOC slaves have xfds_RecogSegment and xfds_DecrunchSegment
  34. initialized, XFDPFB_DATA slaves use xfds_ScanData and xfds_VerifyData.
  35.  
  36. All routines have one thing in common: the CPU registers D0/D1/A0/A1 are
  37. so-called scratch registers, they may change during execution, all other
  38. registers must remain unchanged. CPU register A6 holds a pointer to the
  39. xfdMasterBase structure. See chapters below for a description of the slave
  40. routines.
  41.  
  42. ALL SLAVE ROUTINES MUST BE REENTRANT! NEVER STORE ANY DATA IN STATIC MEMORY
  43. AREAS, USE THE STACK OR SOME ALLOCATED MEMORY INSTEAD! REMEMBER THAT THE
  44. ROUTINES MIGHT BE CALLED BY SEVERAL PROGRAMS AT THE SAME TIME!
  45.  
  46. The name of the packer that is supported by the slave and the flags that
  47. describe the packer are stored in xfds_PackerName and xfds_PackerFlags.
  48.  
  49. (V36) Internal slaves all have an unique ID value stored in xfds_SlaveID.
  50. This field should be set to NULL for external slaves.
  51.  
  52. (V36) If you have written a slave that should replace an internal one
  53. because it's faster or otherwise enhanced, simply put the ID of the slave
  54. to be replaced in xfds_ReplaceID. The old slave will then be taken out of
  55. the list of used slaves. Otherwise, xfds_ReplaceID must be NULL.
  56.  
  57. (V36) xfdRecogBuffer() usually only requires a quite small part of a file
  58. to recognize it properly. To avoid reading the whole file for recognition
  59. purposes, you may set xfds_MinBufferSize to the minimum amount of bytes
  60. that is required to recognize the crunched file correctly.
  61. Note that xfdRecogBuffer() uses this value internally to decide whether
  62. a file might be crunched with a packer or not, so you don't have to do
  63. an extra size comparison in your xfds_RecogBuffer function any more.
  64. For packer headers with non-constant sizes, simply set xfds_MinBufferSize
  65. to a value that will ensure correct recognition of all possible files.
  66.  
  67. Whenever you intend to use features of the xfdmaster.library in your slaves
  68. that are marked (V34) or higher, make sure to set xfds_MasterVersion to
  69. the desired version number, otherwise an old library version might crash
  70. while using the new slave.
  71.  
  72. xfdSlave/--HowToStart--                               xfdSlave/--HowToStart--
  73.  
  74. Some notes how data slaves need to be designed (in assembler). There are
  75. 2 different types of data slaves. The easy ones and the complicated ones.
  76.  
  77. An example header for an easy slave (needs V39) may look like that:
  78.  
  79. S_TEST        DC.L    0        ;no more slaves
  80.         DC.W    2        ;version
  81.         DC.W    39        ;master version
  82.         DC.L    N_TEST        ;name
  83.         DC.W    XFDPFF_DATA|XFDPFF_USERTARGET|XFDPFF_RECOGLEN
  84.         DC.W    0
  85.         DC.L    RB_TEST        ;recog buffer
  86.         DC.L    DB_TEST        ;decrunch buffer
  87.         DC.L    SD_TEST    ; or 0
  88.         DC.L    VD_TEST    ; or 0
  89.         DC.W    0,0
  90.         DC.L    12        ;minimum size
  91. N_TEST        DC.B    "Test Cruncher",0
  92.  
  93. The recognition function checks if the file is known and inserts the
  94. minimum and final buffer sizes into the recog structure. If possible
  95. also a minimum source size (normally the header size + crunched size)
  96. is entered, which is used for corruption checks.
  97.  
  98. RB_TEST        MOVEQ    #0,D0
  99.         CMP.L    #"TEST",(A0)
  100.         BNE.B    .Exit
  101.         MOVE.L    4(A0),xfdrr_FinalTargetLen(A1)
  102.         MOVE.L    4(A0),xfdrr_MinTargetLen(A1)
  103.         MOVE.L    8(A0),D0
  104.         ADD.L    #12,D0
  105.         MOVE.L    D0,xfdrr_MinSourceLen(A1)
  106.         MOVEQ    #1,D0
  107. .Exit        RTS
  108.  
  109. Now the decrunch function is really easy. It gets the buffers and
  110. starts the decruncher (size maybe taken from the structure also).
  111.  
  112. DB_TEST        MOVEM.L    D2-D7/A2-A6,-(A7)
  113.         MOVE.L    xfdbi_UserTargetBuf(A0),A1    * destination
  114.         MOVE.L    xfdbi_SourceBuffer(A0),A0    * source
  115.  
  116.         BSR.B    D_TEST         * returns 0 (error) or 1
  117.  
  118.         MOVEM.L    (A7)+,D2-D7/A2-A6
  119.         RTS
  120.  
  121. Keep in mind, that the decruncher is not allowed to use any global
  122. variables! If you have decrunch code using local variables, modify it
  123. to use the stack (e.g. using LINK command) or allocate your own
  124. bufferes, if stack usage would exceed 1KB. The register A6 contains
  125. xfdMasterBase. To get ExecBase do not use
  126.     MOVEA.L    4.W,A6
  127. but use
  128.     MOVEA.L    xfdm_ExecBase(A6),A6
  129. Often it is not necessary to use stack, but instead optimizing the code
  130. and removing useless register moves allows to store all data in registers.
  131.  
  132. If possible also a scanner maybe added. This allows to use the scan data
  133. functions. This is not necessary, but if possible it can be done very
  134. easy.
  135.  
  136. SD_TEST        MOVEQ    #0,D0
  137.         CMP.L    #"TEST",(A0)
  138.         BNE.B    .Exit
  139.         MOVEQ    #1,D0
  140. .Exit        RTS
  141.  
  142. VD_TEST        MOVEQ    #12,D1
  143.         ADD.L    8(A0),D1    * crlen
  144.         CMP.L    D0,D1        * crlen > buflen ??
  145.         BGT.B    .Exit
  146.         MOVE.L    4(A0),D0
  147.         SUB.L    8(A0),D0    * cr > uncr ??
  148.         BMI.B    .Exit
  149.         MOVE.L    D1,D0        * return size
  150.         RTS
  151. .Exit        MOVEQ    #0,D0
  152.         RTS
  153.  
  154. The second data client type is more complicated and for types, which do
  155. not allow to determine the destination size on recognition and need to
  156. allocate the buffers themself. See examples to find out how this is done.
  157.  
  158. There are other slave types (address and executable slaves). These
  159. types always need to allocate their own buffers and are more complicated.
  160. Check the examples and the docs to learn more about them. Most of these
  161. slave types are internal.
  162.  
  163. xfdSlave/DecrunchBufferXYZ                         xfdSlave/DecrunchBufferXYZ
  164.  
  165.    NAME
  166.         DecrunchBufferXYZ -- Decrunch file from buffer to buffer.
  167.  
  168.    SYNOPSIS
  169.         result = DecrunchBufferXYZ(bufferinfo)
  170.           D0                           A0
  171.  
  172.         BOOL DecrunchBufferXYZ(struct xfdBufferInfo *);
  173.  
  174.    FUNCTION
  175.         The typical steps of such a routine are:
  176.         - Get length of decrunched file (exactly or a bit too much).
  177.         - Allocate memory (with memtype from xfdbi_TargetBufMemType).
  178.         - Decrunch file from xfdbi_SourceBuffer to xfdbi_TargetBuffer.
  179.         - Initialize all necessary parts of the xfdBufferInfo structure.
  180.         - Set xfdbi_Error if an error occurs.
  181.  
  182.         (V38) It's possible to support decrunching to user buffers.
  183.         This looks something like that:
  184.         - Decrunch file from xfdbi_SourceBuffer to xfdbi_UserTargetBuf.
  185.         - Initialize all necessary parts of the xfdBufferInfo structure.
  186.         - Set xfdbi_Error if an error occurs.
  187.         The XFDPFF_USERTARGET flag must be set in the xfdSlave structure if
  188.         it supports this feature. Whether to allocate an own buffer or use
  189.         the given buffer by the user is determined with XFDFF_USERTARGET in
  190.         the xfdBufferInfo structure.
  191.  
  192.         (V39) xfdmaster.library automatically allocates the buffer when not
  193.         supplied by caller program. You need to set XFDPFF_USERTARGET to use
  194.         that feature. When the Recog function return buffer size -1 (no size
  195.         detection case), buffer allocation is skipped. If the slave returns
  196.         -1 in some cases, you still need to do self-allocation, when
  197.         XFDFF_USERTARGET is not set.
  198.  
  199.    INPUTS
  200.         bufferinfo - A valid xfdBufferInfo structure that successfully went
  201.                      through a call to xfdRecogBuffer().
  202.  
  203.    RESULT
  204.         result - TRUE if decrunching succeeded, FALSE if something went wrong.
  205.  
  206.    NOTE
  207.         You have to initialize xfds_DecrunchBuffer with a pointer to your
  208.         DecrunchBufferXYZ routine.
  209.  
  210.    SEE ALSO
  211.         Example sourcecodes.
  212.  
  213. xfdSlave/DecrunchSegmentXYZ                       xfdSlave/DecrunchSegmentXYZ
  214.  
  215.    NAME
  216.         DecrunchSegmentXYZ -- Decrunch segment list.
  217.  
  218.    SYNOPSIS
  219.         result = DecrunchSegmentXYZ(segmentinfo)
  220.           D0                             A0
  221.  
  222.         BOOL DecrunchSegmentXYZ(struct xfdSegmentInfo *);
  223.  
  224.    FUNCTION
  225.         There are two possibilities how to decrunch a segment list. The
  226.         first one works like this:
  227.         - Modify decrunch header to make it return to the caller.
  228.         - Call decrunch header.
  229.         - dos.library/UnloadSeg() whole seglist and clear xfdsi_SegList
  230.           if an error occurs and the seglist has already been altered
  231.           in any way.
  232.         - Otherwise only release segments that are no longer necessary.
  233.         - Store BPTR to first hunk of decrunched segment list in
  234.           xfdsi_SegList.
  235.         - Set xfdsi_Error if an error occurs.
  236.  
  237.         The second possibility works the same way as the first with
  238.         the difference that you don't jump to the original code, but you
  239.         include all necessary parts of it (decrunch routine, relocator)
  240.         in your own routine. The big advantage is that you can handle
  241.         error conditions much better because most of the standard decrunch
  242.         headers in executable files have problems with low memory etc.
  243.  
  244.         (V34) If the decruncher allows it, always support XFDPFB_RELMODE.
  245.         That way the caller can determine the type of memory the segments
  246.         should be placed in by initializing xfdsi_RelMode with XFDREL_#?.
  247.  
  248.         Many crunchers don't change the hunk structure of the crunched
  249.         data. If this is the case, you can simply call the decrunch code
  250.         in the segment list and then use xfdRelocate() (V34).
  251.  
  252.    INPUTS
  253.         segmentinfo - A valid xfdSegmentInfo structure that successfully went
  254.                       through a call to xfdRecogSegment().
  255.  
  256.    RESULT
  257.         result - TRUE if decrunching succeeded, FALSE if something went wrong.
  258.  
  259.    NOTE
  260.         You have to initialize xfds_DecrunchSegment with a pointer to your
  261.         DecrunchSegmentXYZ routine.
  262.  
  263.    SEE ALSO
  264.         Example sourcecodes.
  265.  
  266. xfdSlave/RecogBufferXYZ                               xfdSlave/RecogBufferXYZ
  267.  
  268.    NAME
  269.         RecogBufferXYZ -- Recognize crunched file in buffer.
  270.  
  271.    SYNOPSIS
  272.         result = RecogBufferXYZ(buffer, length, rr(V38))
  273.           D0                      A0      D0    A1
  274.  
  275.         BOOL RecogBufferXYZ(APTR, ULONG, struct xfdRecogResult * (V38));
  276.  
  277.    FUNCTION
  278.         This routine should examine the buffer for a crunched file.
  279.         First thing is to check if the size of the file allows it to
  280.         be crunched with the packer in question. After that, simply
  281.         do some compares to figure out if the file has been crunched
  282.         or not.
  283.  
  284.         (V36) You don't have to do any size comparisons if you set
  285.         xfds_MinBufferSize to the minimum amount of bytes that are
  286.         necessary for a file to be crunched with that packer.
  287.  
  288.         (V38) If it's easily possible to determine the length of the
  289.         uncrunched file and the required memory for decrunching already
  290.         in crunched state (only within xfds_MinBufferSize bytes),
  291.         initialize the xfdRecogResult structure with the correct values.
  292.         Set the XFDPFF_RECOGLEN flag in your slave in that case.
  293.         If it's not sure that you can extract the correct lengths only
  294.         from within the given buffer (eg. PowerPacker data files), set
  295.         the flag, support xfdRecogResult and set xfdrr_MinTargetLen and
  296.         xfdrr_FinalTargetLen to -1.
  297.         
  298.         (V39) Set xfdrr_MinSourceLen to source length to allow buffer
  299.         truncation checks. The master library checks the source buffer
  300.         size against that value before calling the decrunch function.
  301.         Remember: the size includes header size!
  302.         Ignore that field if you do not know source data size.
  303.  
  304.    INPUTS
  305.         buffer - Pointer to a buffer that holds the crunched file.
  306.         length - Length of that buffer.
  307.         rr     - (V38) Pointer to xfdRecogResult structure.
  308.  
  309.    RESULT
  310.         result - TRUE if packer has been recognized, else FALSE.
  311.  
  312.    NOTE
  313.         You have to initialize xfds_RecogBuffer with a pointer to your
  314.         RecogBufferXYZ routine.
  315.  
  316.         (V38) The determined xfdrr_MinTargetLen value should be exactly
  317.         correct, otherwise the whole thing is quite meaningless.
  318.  
  319.    SEE ALSO
  320.         Example sourcecodes.
  321.  
  322. xfdSlave/RecogSegmentXYZ                             xfdSlave/RecogSegmentXYZ
  323.  
  324.    NAME
  325.         RecogSegmentXYZ -- Recognize crunched segment list.
  326.  
  327.    SYNOPSIS
  328.         result = RecogSegmentXYZ(seglist)
  329.           D0                       A0
  330.  
  331.         BOOL RecogSegmentXYZ(BPTR);
  332.  
  333.    FUNCTION
  334.         This routine should examine if a segment list is crunched.
  335.         You can check the whole segment list for correct lengths of hunks
  336.         and for contents of hunks if you like. There should be at least
  337.         3 comparations to determine the cruncher.
  338.  
  339.    INPUTS
  340.         seglist - BPTR to first segment.
  341.  
  342.    RESULT
  343.         result - TRUE if packer has been recognized, else FALSE.
  344.  
  345.    NOTE
  346.         You have to initialize xfds_RecogSegment with a pointer to your
  347.         RecogSegmentXYZ routine.
  348.  
  349.    SEE ALSO
  350.         Example sourcecodes.
  351.  
  352. xfdSlave/ScanDataXYZ                                     xfdSlave/ScanDataXYZ
  353.  
  354.    NAME
  355.         ScanDataXYZ -- Recognize crunched data in buffer.
  356.  
  357.    SYNOPSIS
  358.         result = ScanDataXYZ(buffer, length)
  359.           D0                   A0      D0
  360.  
  361.         BOOL ScanDataXYZ(APTR, ULONG);
  362.  
  363.    FUNCTION
  364.         This routine should only test for the usual data ID at exactly the
  365.         address given as buffer. The length is the amount of bytes until
  366.         the end of the whole buffer and is of minor use in this context.
  367.         You may use it if the ID is several bytes long to test if buffer
  368.         is already at its end.
  369.  
  370.    EXAMPLE
  371.         ScanDataS400    moveq   #0,d0
  372.                         cmp.l   #'S400',(a0)    ;StoneCracker Data ID
  373.                         bne.s   .Exit
  374.                         moveq   #1,d0
  375.         .Exit           rts
  376.  
  377.    INPUTS
  378.         buffer - Pointer to a address to scan at.
  379.         length - Length of whole buffer.
  380.  
  381.    RESULT
  382.         result - TRUE if crunched data has been recognized, else FALSE.
  383.  
  384.    NOTE
  385.         You have to initialize xfds_ScanData with a pointer to your
  386.         ScanDataXYZ routine.
  387.  
  388. xfdSlave/VerifyDataXYZ                                 xfdSlave/VerifyDataXYZ
  389.  
  390.    NAME
  391.         VerifyDataXYZ -- Check crunched data and return length.
  392.  
  393.    SYNOPSIS
  394.         length = VerifyDataXYZ(buffer, length)
  395.           D0                     A0      D0
  396.  
  397.         ULONG VerifyDataXYZ(APTR, ULONG);
  398.  
  399.    FUNCTION
  400.         This routine is called after ScanDataXYZ and first has to check if
  401.         the data ID found while scanning is part of a valid data file or
  402.         just some piece of code etc.
  403.  
  404.         If it is a valid data file, it has to calculate the final length
  405.         of the data file starting at the ID until the end. This value will
  406.         then be used for the xfdScanNode structure.
  407.  
  408.    EXAMPLE
  409.         VerifyDataS400  moveq   #$c,d1
  410.                         add.l   8(a0),d1        ;crlen
  411.                         cmp.l   d0,d1           ;crlen > buflen ??
  412.                         bgt.s   .Exit
  413.                         move.l  4(a0),d0
  414.                         sub.l   8(a0),d0        ;cr > uncr ??
  415.                         bmi.s   .Exit
  416.                         move.l  d1,d0
  417.                         rts
  418.         .Exit           moveq   #0,d0
  419.                         rts
  420.  
  421.    INPUTS
  422.         buffer - Pointer to start address of possible data file.
  423.         length - Length of whole buffer.
  424.  
  425.    RESULT
  426.         length - Final length of found data file, else NULL.
  427.  
  428.    NOTE
  429.         You have to initialize xfds_VerifyData with a pointer to your
  430.         VerifyDataXYZ routine.
  431.  
  432.